package cn.nawang.ebeim.client.version;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import cn.nawang.ebeim.client.bean.DbVersionTreeBean;

public class DirectoryNode implements Node {

  private static final long serialVersionUID = 2L;
  private String nid;
  private String pid;
  private String name;
  private String dsId;
  private Node parent;
  private boolean isHandAdd = false;
  private long createTime;
  private byte status = Node.STATUS_NOOP;
  private Map<String, Node> children = new HashMap<String, Node>();
  
  public long getCreateTime() {
    return createTime;
  }

  public void setCreateTime(long createTime) {
    this.createTime = createTime;
  }

  public boolean isHandAdd() {
    return isHandAdd;
  }

  public void setHandAdd(boolean isHandAdd) {
    this.isHandAdd = isHandAdd;
  }

  public String getDsId() {
    return dsId;
  }

  public void setDsId(String dsId) {
    this.dsId = dsId;
  }

  public String getPid() {
    return pid;
  }

  public void setPid(String pid) {
    this.pid = pid;
  }

  public String getNid() {
    return nid;
  }

  public void setNid(String nid) {
    this.nid = nid;
  }

  public DirectoryNode() {
    super();
  }

  public DirectoryNode(String name) {
    super();
    this.name = name;
  }

  public Map<String, Node> getChildren() {
    return children;
  }
  
  @Override
  public void addToList(String dsId,String version,List<DbVersionTreeBean> beans) {
    
    DbVersionTreeBean treeBean = new DbVersionTreeBean();
    treeBean.setDsId(dsId);
    treeBean.setId(getNid());
    treeBean.setPid(getPid());
    treeBean.setName(getName());
    treeBean.setStatus(getStatus());
    treeBean.setVersion(version);
    beans.add(treeBean);
    
    for (String key : children.keySet()) {
      Node node = children.get(key);
      node.addToList(dsId,version,beans);
    }
  };

  @Override
  public void visit() {
    VersionTree.count++;
    String path = "";
    if (parent != null) {
      path = parent.getName();
      if (!path.equals("/")) {
        path += "/";
      }
    }
    System.out.println(path + name + "\t" + getStatus()+"\t"+getNid()+"\t"+getPid());
    for (String key : children.keySet()) {
      Node node = children.get(key);
      node.visit();
    }

  }

  @Override
  public boolean traverse(NodeOp op) {
    for (Node node : children.values()) {
      node.traverse(op);
    }
    return true;
  }

  public void addNode(Node node) {
    children.put(node.getName(), node);
    node.setParent(this);
  }

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public void setChildren(Map<String, Node> children) {
    this.children = children;
  }

  public Node getParent() {
    return parent;
  }

  public void setParent(Node parent) {
    this.parent = parent;
  }
  
  public void mergeAll(Node node) {
    DirectoryNode dn = (DirectoryNode) node;
    if (this.getName().equals(node.getName())) {
      Map<String, Node> nodes = dn.getChildren();
      List<Node> newNodes = new ArrayList<Node>();
      setStatus(STATUS_NO_CHANGE);
      for (String key : nodes.keySet()) {
        if (children.get(key) != null) {
          children.get(key).mergeAll(nodes.get(key));

        } else {
          newNodes.add(nodes.get(key));
        }
      }
      for (Node n : newNodes) {
        if(n.getStatus() == Node.STATUS_DELETED){
          n.setDeleteStatus(Node.STATUS_BEFORE_DELETED);
        }else if(n.getStatus() != Node.STATUS_BEFORE_DELETED){
          n.setDeleteStatus(Node.STATUS_DELETED);
        }
        n.setPid(this.getNid());
        this.addNode(n);
      }
    }

  }
  
  public void setDeleteStatus(byte status){
    this.setStatus(status);
    Map<String, Node> nodes = this.getChildren();
    for (String key : nodes.keySet()) {
      Node children = nodes.get(key);
      children.setDeleteStatus(status);
    }
    
  }

  @Override
  public void merge(Node node) {
    DirectoryNode dn = (DirectoryNode) node;
    if (this.getName().equals(node.getName())) {
      Map<String, Node> nodes = dn.getChildren();
      List<Node> newNodes = new ArrayList<Node>();
      setStatus(STATUS_NO_CHANGE);
      for (String key : nodes.keySet()) {
        if (children.get(key) != null) {
          children.get(key).merge(nodes.get(key));

        } else {
          newNodes.add(nodes.get(key));
        }

      }
      for (Node n : newNodes) {
        this.addNode(n);
        n.setStatus(Node.STATUS_ADD);
      }
    }

  }

  @Override
  public boolean filterChanges(List<Node> list) {
    boolean flag = false;

    for (Node n : children.values()) {
      if (n.filterChanges(list)) {
        flag = true;
      }
    }

    return flag;

  }


  @Override
  public String toString() {
    return "DirectoryNode [nid=" + nid + ", pid=" + pid + ", name=" + name + ", dsId=" + dsId
        + ", status=" + status + "]";
  }

  @Override
  public byte getStatus() {
    return status;
  }

  @Override
  public void setStatus(byte status) {
    this.status = status;
  }

  @Override
  public boolean filter(List<Node> list, Filter filter) {
    boolean flag = false;

    for (Node n : children.values()) {
      flag = n.filter(list, filter);
    }

    return flag;
  }

  @Override
  public String getPath() {
    if (getParent() != null) {
      return getParent().getPath() + File.separator + getName();
    }
    return "";
  }

}
